<template>
	<div class="sc-upload" :class="{ 'sc-upload-round': round }" :style="style">
		<div
			v-if="file && file.status != 'success'"
			class="sc-upload__uploading"
		>
			<div class="sc-upload__progress">
				<el-progress
					:percentage="file.percentage"
					:text-inside="true"
					:stroke-width="16"
				/>
			</div>
			<el-image class="image" :src="file.tempFile" fit="cover"></el-image>
		</div>
		<div v-if="file && file.status == 'success'" class="sc-upload__img">
			<el-image
				class="image"
				:src="file.url"
				:preview-src-list="[file.url]"
				fit="cover"
				hide-on-click-modal
				append-to-body
				:z-index="9999"
			>
				<template #placeholder>
					<div class="sc-upload__img-slot">Loading...</div>
				</template>
			</el-image>
			<div class="sc-upload__img-actions" v-if="!disabled">
				<span class="del" @click="handleRemove()"
					><el-icon><el-icon-delete /></el-icon
				></span>
			</div>
		</div>
		<el-upload
			v-if="!file"
			class="uploader"
			ref="uploader"
			:auto-upload="cropper ? false : autoUpload"
			:disabled="disabled"
			:show-file-list="showFileList"
			:action="action"
			:name="name"
			:data="data"
			:accept="accept"
			:limit="1"
			:objName="objName"
			:orgCode="orgCode"
			:http-request="request"
			:on-change="change"
			:before-upload="before"
			:on-success="success"
			:on-error="error"
			:on-exceed="handleExceed"
			:uploadType="uploadType"
			:bucketName="bucketName"
		>
			<slot>
				<div class="el-upload--picture-card">
					<div class="file-empty">
						<el-icon><component :is="icon" /></el-icon>
						<h4 v-if="title">{{ title }}</h4>
					</div>
				</div>
			</slot>
		</el-upload>
		<span style="display: none !important"
			><el-input v-model="value"></el-input
		></span>
		<el-dialog
			title="剪裁"
			draggable
			v-model="cropperDialogVisible"
			:width="580"
			@closed="cropperClosed"
			destroy-on-close
		>
			<sc-cropper
				:src="cropperFile.tempCropperFile"
				:compress="compress"
				:aspectRatio="aspectRatio"
				ref="cropper"
			></sc-cropper>
			<template #footer>
				<el-button @click="cropperDialogVisible = false"
					>取 消</el-button
				>
				<el-button type="primary" @click="cropperSave">确 定</el-button>
			</template>
		</el-dialog>
	</div>
</template>

<script>
import { defineAsyncComponent } from "vue";
import { genFileId } from "element-plus";
const scCropper = defineAsyncComponent(() => import("@/components/scCropper"));
import config from "@/config/upload";

export default {
	props: {
		modelValue: { type: String, default: "" },
		height: { type: Number, default: 148 },
		width: { type: Number, default: 148 },
		title: { type: String, default: "" },
		icon: { type: String, default: "el-icon-plus" },
		action: { type: String, default: "" },
		apiObj: { type: Object, default: () => {} },
		name: { type: String, default: config.filename },
		data: { type: Object, default: () => {} },
		accept: { type: String, default: "image/gif, image/jpeg, image/png" },
		maxSize: { type: Number, default: config.maxSizeFile },
		limit: { type: Number, default: 1 },
		objName: { type: String, default: "" },
		orgCode: { type: String, default: "" },
		autoUpload: { type: Boolean, default: true },
		showFileList: { type: Boolean, default: false },
		disabled: { type: Boolean, default: false },
		round: { type: Boolean, default: false },
		onSuccess: {
			type: Function,
			default: () => {
				return true;
			},
		},

		cropper: { type: Boolean, default: false },
		compress: { type: Number, default: 1 },
		aspectRatio: { type: Number, default: NaN },
		uploadType: { type: String, default: ""},
		bucketName: { type: String, default: ""},
	},
	components: {
		scCropper,
	},
	data() {
		return {
			value: "",
			file: null,
			style: {
				width: this.width + "px",
				height: this.height + "px",
			},
			cropperDialogVisible: false,
			cropperFile: null,
		};
	},
	watch: {
		modelValue(val) {
			this.value = val;
			this.newFile(val);
		},
		value(val) {
			this.$emit("update:modelValue", val);
		},
	},
	mounted() {
		this.value = this.modelValue;
		this.newFile(this.modelValue);
	},
	methods: {
		newFile(url) {
			if (url) {
				this.file = {
					status: "success",
					url: url,
				};
			} else {
				this.file = null;
			}
		},
		cropperSave() {
			this.$refs.cropper.getCropFile(
				(file) => {
					file.uid = this.cropperFile.uid;
					this.cropperFile.raw = file;

					this.file = this.cropperFile;
					this.file.tempFile = URL.createObjectURL(this.file.raw);
					this.$refs.uploader.submit();
				},
				this.cropperFile.name,
				this.cropperFile.type
			);
			this.cropperDialogVisible = false;
		},
		cropperClosed() {
			URL.revokeObjectURL(this.cropperFile.tempCropperFile);
			delete this.cropperFile.tempCropperFile;
		},
		handleRemove() {
			this.clearFiles();
		},
		clearFiles() {
			URL.revokeObjectURL(this.file.tempFile);
			this.value = "";
			this.file = null;
			this.$nextTick(() => {
				this.$refs.uploader.clearFiles();
			});
		},
		change(file, files) {
			if (files.length > 1) {
				files.splice(0, 1);
			}
			if (this.cropper && file.status == "ready") {
				const acceptIncludes = [
					"image/gif",
					"image/jpeg",
					"image/png",
				].includes(file.raw.type);
				if (!acceptIncludes) {
					this.$notify.warning({
						title: "上传文件警告",
						message: "选择的文件非图像类文件",
					});
					return false;
				}
				this.cropperFile = file;
				this.cropperFile.tempCropperFile = URL.createObjectURL(
					file.raw
				);
				this.cropperDialogVisible = true;
				return false;
			}
			this.file = file;
			if (file.status == "ready") {
				file.tempFile = URL.createObjectURL(file.raw);
			}
		},
		before(file) {
			const acceptIncludes = this.accept
				.replace(/\s/g, "")
				.split(",")
				.includes(file.type);
			if (!acceptIncludes) {
				this.$notify.warning({
					title: "上传文件警告",
					message: "选择的文件非图像类文件",
				});
				this.clearFiles();
				return false;
			}
			const maxSize = file.size / 1024 / 1024 < this.maxSize;
			if (!maxSize) {
				this.$message.warning(
					`上传文件大小不能超过 ${this.maxSize}MB!`
				);
				this.clearFiles();
				return false;
			}
		},
		handleExceed(files) {
			const file = files[0];
			file.uid = genFileId();
			this.$refs.uploader.handleStart(file);
		},
		// success(res, file) {
		// 	//释放内存删除blob
		// 	URL.revokeObjectURL(file.tempFile);
		// 	delete file.tempFile;
		// 	var os = this.onSuccess(res, file);
		// 	if (os != undefined && os == false) {
		// 		this.$nextTick(() => {
		// 			this.file = null;
		// 			this.value = "";
		// 		});
		// 		return false;
		// 	}
		// 	var response = config.parseData(res);
		// 	file.url = response.src;
		// 	this.value = file.url;
		// },
		success(res, file) {
			var os = this.onSuccess(res, file);
			if (os != undefined && os == false) {
				return false;
			}
			//var response = config.parseData(res);
			if (res && res.status == 200) {
				file.name = res.response;
				file.realUrl = res.response;

				file.url = res.response;
				this.value = file.url;
				return false;
			}
		},
		error(err) {
			this.$nextTick(() => {
				this.clearFiles();
			});
			this.$notify.error({
				title: "上传文件未成功",
				message: err,
			});
		},
		// request(param) {
		// 	// eslint-disable-next-line no-debugger
		// 	//debugger;
		// 	var apiObj = config.apiObj;
		// 	if (this.apiObj) {
		// 		apiObj = this.apiObj;
		// 	}
		// 	const data = new FormData();
		// 	data.append(param.filename, param.file);
		// 	data.append("objName", "order");
		// 	data.append("orgCode", "00001");
		// 	for (const key in param.data) {
		// 		data.append(key, param.data[key]);
		// 	}
		// 	apiObj
		// 		.post(data, {
		// 			onUploadProgress: (e) => {
		// 				const complete = parseInt(
		// 					((e.loaded / e.total) * 100) | 0,
		// 					10
		// 				);
		// 				param.onProgress({ percent: complete });
		// 			},
		// 		})
		// 		.then((res) => {
		// 			var response = config.parseData(res);
		// 			if (response.code == config.successCode) {
		// 				param.onSuccess(res);
		// 			} else {
		// 				param.onError(response.msg || "未知错误");
		// 			}
		// 		})
		// 		.catch((err) => {
		// 			param.onError(err);
		// 		});
		// },
		async request(param) {
			// eslint-disable-next-line no-debugger
			////debugger;
			var apiObj = config.apiObj;
			if (this.apiObj) {
				apiObj = this.apiObj;
			}
			var requestId = this.getFilelastModified();
			//上传文件单片2MB
			var chunkSize = 1024 * 1024 * 2;
			// 总分片数量
			var chunks = Math.ceil(param.file.size / chunkSize);
			for (let index = 0; index < chunks; index++) {
				var tempFile = null;
				if (index === chunks - 1) {
					tempFile = param.file.slice(index * chunkSize);
				} else {
					tempFile = param.file.slice(
						index * chunkSize,
						(index + 1) * chunkSize
					);
				}
				//if (index > 0)
					// eslint-disable-next-line no-debugger
					//debugger;
				const data = new FormData();
				data.append("data", tempFile);
				// data.append("data", param.file);
				data.append("requestId", requestId);
				data.append("total", chunks);
				data.append("index", index);
				data.append("fileName", param.file.name);
				data.append("fileType", param.file.type);
				data.append("objName", this.objName);
				data.append("orgCode", this.orgCode);
				data.append("uploadType", this.uploadType);
				data.append("bucketName", this.bucketName);
				for (const key in param.data) {
					data.append(key, param.data[key]);
				}
				await apiObj
					.post(data, {
						onUploadProgress: (e) => {
							const complete = parseInt(
								(((index + 1) * 100) / chunks) | 0,
								10
							);
							console.log(e.loaded, e.total);
							param.onProgress({ percent: complete });
						},
					})
					.then((res) => {
						// eslint-disable-next-line no-debugger
						////debugger
						if (res.status != 200) {
							param.onError("上传失败");
							return;
						} else {
							param.onSuccess(res);
						}
					})
					.catch((err) => {
						param.onError(err);
						return;
					});
			}
		},
		getFilelastModified: function () {
			var dd = new Date();
			return (
				dd.getFullYear().toString() +
				dd.getMonth().toString() +
				dd.getDate().toString() +
				dd.getHours().toString() +
				dd.getMinutes().toString() +
				dd.getSeconds().toString() +
				dd.getMilliseconds().toString()
			);
		},
	},
};
</script>

<style scoped>
.el-form-item.is-error .sc-upload .el-upload--picture-card {
	border-color: var(--el-color-danger);
}
.sc-upload .el-upload--picture-card {
	border-radius: 0;
}

.sc-upload .uploader,
.sc-upload:deep(.el-upload) {
	width: 100%;
	height: 100%;
}

.sc-upload__img {
	width: 100%;
	height: 100%;
	position: relative;
}
.sc-upload__img .image {
	width: 100%;
	height: 100%;
}
.sc-upload__img-actions {
	position: absolute;
	top: 0;
	right: 0;
	display: none;
}
.sc-upload__img-actions span {
	display: flex;
	justify-content: center;
	align-items: center;
	width: 25px;
	height: 25px;
	cursor: pointer;
	color: #fff;
}
.sc-upload__img-actions span i {
	font-size: 12px;
}
.sc-upload__img-actions .del {
	background: #f56c6c;
}
.sc-upload__img:hover .sc-upload__img-actions {
	display: block;
}
.sc-upload__img-slot {
	display: flex;
	justify-content: center;
	align-items: center;
	width: 100%;
	height: 100%;
	font-size: 12px;
	background-color: var(--el-fill-color-lighter);
}

.sc-upload__uploading {
	width: 100%;
	height: 100%;
	position: relative;
}
.sc-upload__progress {
	position: absolute;
	width: 100%;
	height: 100%;
	display: flex;
	justify-content: center;
	align-items: center;
	background-color: var(--el-overlay-color-lighter);
	z-index: 1;
	padding: 10px;
}
.sc-upload__progress .el-progress {
	width: 100%;
}
.sc-upload__uploading .image {
	width: 100%;
	height: 100%;
}

.sc-upload .file-empty {
	width: 100%;
	height: 100%;
	display: flex;
	justify-content: center;
	align-items: center;
	flex-direction: column;
}
.sc-upload .file-empty i {
	font-size: 28px;
}
.sc-upload .file-empty h4 {
	font-size: 12px;
	font-weight: normal;
	color: #8c939d;
	margin-top: 8px;
}

.sc-upload.sc-upload-round {
	border-radius: 50%;
	overflow: hidden;
}
.sc-upload.sc-upload-round .el-upload--picture-card {
	border-radius: 50%;
}
.sc-upload.sc-upload-round .sc-upload__img-actions {
	top: auto;
	left: 0;
	right: 0;
	bottom: 0;
}
.sc-upload.sc-upload-round .sc-upload__img-actions span {
	width: 100%;
}
</style>
